/*
 * Wikikat -  A software to help in the categorization of Wikipedia articles.
 * Copyright (C) 2011 Asier Sarasua Garmendia
 *
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 * 
 * Hau software librea da.
 */

Components.utils.import("resource://gre/modules/Services.jsm");

var wikikat = {

  curVersion: "2.0",
  profileURI: Services.dirsvc.get("ProfD", Components.interfaces.nsIFile),
  prefs: Services.prefs.getBranch("extensions.wikikat."),

  init: function() {
    var firstrun = wikikat.prefs.getBoolPref("firstrun");

    // Register to receive notifications of preference changes
    Services.prefs.addObserver("extensions.wikikat.", this, false);

    if (firstrun) {
      wikikat.prefs.setBoolPref("firstrun", false);
      wikikat.prefs.setCharPref("installedVersion", this.curVersion);

      /* Add Wikikat button to the navigation bar and force
       * the toolbar to be displayed */
      var wikikatButtonId = "wikikat-button";
      var navBarId = "nav-bar";
      var navBar = $(navBarId);

      var currentSet = navBar.currentSet;

      // Append only if the button is not already there
      var curSet = currentSet.split(",");
      if (curSet.indexOf(wikikatButtonId) == -1) {
        var set = curSet.concat(wikikatButtonId).join(",");

        navBar.currentSet = set;
        navBar.setAttribute("currentset", set);
        document.persist(navBarId, "currentset");

        try {
          BrowserToolboxCustomizeDone(true);
        } catch (e) {
        }
      }
    }
  },

  onToolbarButtonCommand: function(e) {
      var slug ="wikikat";
      var numTabs = gBrowser.tabs.length;
      var found = false;
      var index = 0;

      while (index < numTabs && !found) {
        var currentTab = gBrowser.tabs[index];

        if (currentTab.hasAttribute('slug')
            && currentTab.getAttribute('slug') == slug) {

          var currentBrowser = gBrowser.getBrowserAtIndex(index);
          currentBrowser.webNavigation.loadURI("chrome://wikikat/content/options.xul", null, null,
                                               null, null);
          found = true;
        }
        index++;
      }

      if (!found) {
        var newTab = gBrowser.addTab("chrome://wikikat/content/options.xul");
        // Store slug as an attribute for reusing purposes
        newTab.setAttribute('slug', slug);
        gBrowser.selectedTab = newTab;
      }
  },
 
  goOnKey: function(event) {
    if (event.keyCode == 13) {
      document.getElementById("wkPtext").value ="";
      var sLang = wikikat.prefs.getCharPref("source");
      var iWiki = wikikat.prefs.getBoolPref("iwiki");
      var url = "http://"+sLang+".wikipedia.org/wiki/"+document.getElementById("wkPword").value;

      //Remove cat buttons
      var newcatbuttons = document.getElementById("wkPnewcats");
      while (newcatbuttons.firstChild) {
        newcatbuttons.removeChild(newcatbuttons.firstChild);
      }

      this.ajax({
        url: url,
        onSuccess: function (data) {
          var wikidomdata = wikikat.parser(data);
          var maintxtbox = document.getElementById("wkPtext");
          //Interwikis
          var siwiki = wikidomdata.getElementsByTagName("h1")[0].getElementsByTagName("span")[0].textContent;
          maintxtbox.value = maintxtbox.value+"[["+sLang+":"+siwiki+"]]\n\n";
          if (iWiki == true) {
            var iwikis = new Array();
            try {
              var iwiki = wikidomdata.getElementById("p-lang").getElementsByTagName("a");
              for (i in iwiki) {
                var wikilink = iwiki[i].getAttribute("title");
                var wikilang = iwiki[i].getAttribute("lang");
                iwikis[i] = "[["+wikilang+":"+wikilink+"]]";
              }
              iwikis.push("[["+sLang+":"+siwiki+"]]");
              iwikis.sort();
              maintxtbox.value = iwikis.join("\n");
              maintxtbox.value = maintxtbox.value+"\n\n";
            } catch (err) {

            }
          }
          //Categories
          var katwiki = wikidomdata.getElementById("mw-normal-catlinks").getElementsByTagName("ul")[0].getElementsByTagName("a");
          for (i in katwiki) {
            var kat = katwiki[i].getAttribute("title");
            wikikat.targetCats(kat, maintxtbox);
          }
        },
        onError: function () {
          maintxtbox.value = document.getElementById("wikikat-strings").getString('noLoad');
        }
      });
    }
  },

  targetCats: function(kat, atxtbox) {
    var sLang = wikikat.prefs.getCharPref("source");
    var tLang = wikikat.prefs.getCharPref("target");
    var lev = wikikat.prefs.getIntPref("levels");
    var eqCats = wikikat.prefs.getBoolPref("eqcats");
    var url = "http://"+sLang+".wikipedia.org/wiki/"+kat;
    kat = decodeURI(kat);
    this.ajax({
      url: url,
      onSuccess: function (data) {
        var wikidomdata = wikikat.parser(data);

        if (data.indexOf(tLang+".wikipedia.org") != -1) {
          var katwiki = wikidomdata.getElementById("p-lang").getElementsByTagName("a");
          for (i in katwiki) {
            if (katwiki[i].getAttribute("lang") == tLang) {
              var tKat = katwiki[i].getAttribute("title");
              atxtbox.value = atxtbox.value+"[["+tKat+"]]\n";
            }
          }
        } else {
          if (atxtbox.id == "wkPtext") {
            wikikat.populateCatbuttons(kat); //Always create the buttons for new categories 
          }
          if (lev == 2) {
            if (eqCats) {
              atxtbox.value = atxtbox.value+"*"+kat+"\n";
            }
            //Categories2
            var katwiki2 = wikidomdata.getElementById("mw-normal-catlinks").getElementsByTagName("ul")[0].getElementsByTagName("a");
            for (i in katwiki2) {
              var kat2 = katwiki2[i].getAttribute("title");
              wikikat.targetCats2(kat2, atxtbox);
            }
          } else {
            if (eqCats) {
              atxtbox.value = atxtbox.value+"*"+kat+"\n";
            }
          }
        }
      },
      onError: function () {
        if (eqCats) {
          atxtbox.value = atxtbox.value+"*"+kat+"\n";
        }
      }
    });
  },

  targetCats2: function(kat2, atxtbox) {
    var sLang = wikikat.prefs.getCharPref("source");
    var tLang = wikikat.prefs.getCharPref("target");
    var eqCats = wikikat.prefs.getBoolPref("eqcats");
    var url = "http://"+sLang+".wikipedia.org/wiki/"+kat2;
    kat2 = decodeURI(kat2);
    this.ajax({
      url: url,
      onSuccess: function (data) {
        if (data.indexOf(tLang+".wikipedia.org") != -1) {
          var wikidomdata = wikikat.parser(data);

          var katwiki = wikidomdata.getElementById("p-lang").getElementsByTagName("a");
          for (i in katwiki) {
            if (katwiki[i].getAttribute("lang") == tLang) {
              var tKat2 = katwiki[i].getAttribute("title");
              atxtbox.value = atxtbox.value+"\t[["+tKat2+"]]\n";
            }
          }
        } else {
          if (eqCats) {
            atxtbox.value = atxtbox.value+"\t*"+kat2+"\n";
          }
        }
      },
      onError: function () {
        if (eqCats) {
          atxtbox.value = atxtbox.value+"\t*"+kat2+"\n";
        }
      }
    });
  },

  populateCatbuttons: function(kat) {
    var wklab = document.createElement("label");
    var wkcreate = document.createElement("button");
    var wkcheck = document.createElement("button");
    var wkvbox = document.createElement("vbox");
    var wkhbox = document.createElement("hbox");
    var wktextbox = document.createElement("textbox");
    wkhbox.appendChild(wklab);
    wkhbox.appendChild(wkcheck);
    wkhbox.appendChild(wkcreate);
    wkvbox.appendChild(wkhbox);
    wkvbox.appendChild(wktextbox);
    wktextbox.setAttribute("hidden", "true");
    wktextbox.setAttribute("multiline", "true");
    wktextbox.setAttribute("rows", "6");
    document.getElementById("wkPnewcats").appendChild(wkvbox);
    wkvbox.setAttribute("id", "v"+kat);
    wkhbox.setAttribute("id", kat);
    wktextbox.setAttribute("id", "txtbox"+kat);
    wkcreate.setAttribute("id", "create"+kat);
    wkhbox.setAttribute("align", "center");
    wklab.value = kat;
    
    wkcheck.setAttribute("label", document.getElementById("wikikat-strings").getString('checkCats'));
    wkcheck.setAttribute("onclick", "wikikat.checkCats('"+kat+"')");
    wkcreate.setAttribute("label", document.getElementById("wikikat-strings").getString('createCats'));
    wkcreate.setAttribute("hidden", "true");
    wkcreate.setAttribute("onclick", "wikikat.createCat('"+kat+"')");
  },

  checkCats: function(kat) {
    var txtboxs = document.getElementById("wkPnewcats").getElementsByTagName("textbox");
    var thebuttons = document.getElementById("wkPnewcats").getElementsByTagName("button");
    for (i in txtboxs) {
      txtboxs[i].setAttribute("hidden", "true");
    }
    for (i in thebuttons) {
      if (thebuttons[i].label == "Create")  {
        thebuttons[i].hidden = "true";
      }
    }
    var wktextbox = document.getElementById("txtbox"+kat);
    wktextbox.setAttribute("hidden", "false");
    wktextbox.value = "";
    var wkcreate = document.getElementById("create"+kat);
    wkcreate.setAttribute("hidden", "false");    
    wikikat.targetCats(kat, wktextbox);
  },

  createCat: function(kat) {
    var tLang = wikikat.prefs.getCharPref("target");
    var sLang = wikikat.prefs.getCharPref("source");
    var txtboxvalues = document.getElementById("txtbox"+kat).value.trim().split("\n");
    var newkat = txtboxvalues.shift().replace(/\[|\]/g, '').replace(/ /g, '_');
    var superkats = txtboxvalues.join("\n");
    superkats = superkats.replace(/\t/g, "");
    var urlnew = "http://"+tLang+".wikipedia.org/w/index.php?title="+encodeURI(newkat)+"&action=edit"
    var mainWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)  
                   .getInterface(Components.interfaces.nsIWebNavigation)  
                   .QueryInterface(Components.interfaces.nsIDocShellTreeItem)  
                   .rootTreeItem  
                   .QueryInterface(Components.interfaces.nsIInterfaceRequestor)  
                   .getInterface(Components.interfaces.nsIDOMWindow);
    var newTab = mainWindow.gBrowser.addTab(urlnew);
    mainWindow.gBrowser.selectedTab = newTab;
    newTab.setAttribute("id", "createkat");

    //Interwikis
    var url = "http://"+sLang+".wikipedia.org/wiki/"+kat;
    var iwikis = "";
    this.ajax({
      url: url,
      onSuccess: function (data) {

        var wikidomdata = wikikat.parser(data);
        try {
          var iwiki = wikidomdata.getElementById("p-lang").getElementsByTagName("a");
          var iwikis = new Array();
          for (i in iwiki) {
            var wikilink = iwiki[i].getAttribute("title");
            var wikilang = iwiki[i].getAttribute("lang");
            iwikis[i] = "[["+wikilang+":"+wikilink+"]]";
          }
          iwikis.push("[["+sLang+":"+kat+"]]");
          iwikis.sort();
          var iwikisstr = iwikis.join("\n");

          mainWindow.gBrowser.addEventListener("DOMContentLoaded", function (event) {
            var aview = event.originalTarget.defaultView;
            if (aview.location.href.indexOf(encodeURI(newkat)) != -1) {  
              aview.document.getElementById("wpTextbox1").value = superkats+"\n\n"+iwikisstr;
              aview.document.getElementById("wpSummary").value = document.getElementById("wikikat-strings").getString('createdwith'); 
            }
          }, true);

        } catch (err) {

        }
      },
      onError: function () {
          
      }
    });


  },

  /*
   * Ajax stuff
   */

  /* A generic function for performing AJAX requests
   * It takes one argument, which is an object that contains a set of options
   * Thanks for this, John Resig.
   */
  ajax: function (options) {
    // Load the options object with defaults, if no
    // values were provided by the user
    options = {
      // The type of HTTP Request
      type: options.type || "GET",

      // The URL the request will be made to
      url: options.url || "",

      // How long to wait before considering the request to be a timeout
      timeout: options.timeout ||
        wikikat.prefs.getIntPref("timeout") * 1000,

      // Functions to call when the request fails, succeeds,
      // or completes (either fail or succeed)
      onComplete: options.onComplete || function(){},
      onError: options.onError || function(){},
      onSuccess: options.onSuccess || function(){},

      // The data type that'll be returned from the server
      // the default is simply to determine what data was returned from the
      // server and act accordingly.
      data: options.data || ""
    };

    // Create the request object
    var xhr = new XMLHttpRequest();

    // Open the asynchronous POST request
    xhr.open(options.type, options.url, true);

    // We're going to wait for a request for the amount of seconds
    // the user has in its preferences before giving up
    var timeoutLength = wikikat.prefs.getIntPref("timeout") * 1000;

    // Keep track of when the request has been succesfully completed
    var requestDone = false;

    // Initalize a callback which will fire 5 seconds from now, cancelling
    // the request (if it has not already occurred).
    // TODO: determine if the request has actually been timed out
    setTimeout(function () {
      requestDone = true;
    }, timeoutLength);

    // Watch for when the state of the document gets updated
    xhr.onreadystatechange = function() {
      // Wait until the data is fully loaded,
      // and make sure that the request hasn't already timed out
      if (xhr.readyState == 4 && !requestDone) {

        // Check to see if the request was successful
        if (httpSuccess(xhr)) {

          // Execute the success callback with the data returned from the server
          options.onSuccess(httpData(xhr, options.type));

          // Otherwise, an error occurred, so execute the error callback
        } else {
          options.onError();
        }

        // Call the completion callback
        options.onComplete();

        // Clean up after ourselves, to avoid memory leaks
        xhr = null;
      }
    };

    // Establish the connection to the server
    xhr.send();

    // Determine the success of the HTTP response
    function httpSuccess(r) {
      try {
        // If no server status is provided, and we're actually
        // requesting a local file, then it was successful
        return !r.status && location.protocol == "file:" ||
          // Any status in the 200 range is good
          (r.status >= 200 && r.status < 300) ||
          // Successful if the document has not been modified
          r.status == 304;
      } catch (e) {
      }

      // If checking the status failed, then assume that the request failed too
      return false;
    }

    // Extract the correct data from the HTTP response
    function httpData(r, type) {
      // Get the content-type header
      var ct = r.getResponseHeader("content-type");

      // If no default type was provided, determine if some
      // form of XML was returned from the server
      var data = !type && ct && ct.indexOf("xml") >= 0;

      // Get the XML Document object if XML was returned from
      // the server, otherwise return the text contents returned by the server
      data = type == "xml" || data ? r.responseXML : r.responseText;

      // If the specified type is "script", execute the returned text
      // response as if it was JavaScript
      if (type == "script") {
        JSON.parse(data);
      }

      // Return the response data (either an XML Document or a text string)
      return data;
    }

  },

  parser: function (data) {
    var oParser = new DOMParser();
    var wikidomdata = oParser.parseFromString(data, "application/xml");
    return wikidomdata; 
  }
};

window.addEventListener("load", function(e) { wikikat.init(); }, false);
window.addEventListener("unload", function(e) { wikikat.shutdown(); }, false);
